home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
battutor.arc
/
SETDISK.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-05-05
|
15KB
|
315 lines
PAGE 60,132
TITLE SETDISK.COM VER.2.0 14-AUG-83 19:15
comment *
SETDISK.COM
VERSION 2.0 14-AUG-83
Written by Warren Craycroft
6236 Oakdale Ave.
Oakland, CA 94605
(C) 1983 by Warren Craycroft. Permission is granted to copy and
distribute this program, including source code, provided that no
charge shall be made except for a reasonable charge for the media
and handling, and that this notice shall remain intact in all copies.
*
comment *
This program is a utility that can be used with DOS 2.0 to
find the disk drive number that contains a certain file.
SETDISK is similar to FINDFILE, with one additional feature.
When SETDISK finds the file, it sets the DOS default
drive designator to the drive on which the file was found.
A common use of SETDISK is to help a batch file "orient"
itself by discovering on which drive the Batch File itself is
running, and on what drives other files (such as useful system
utilities) can be found. A lot of this orientation can be done
without bothering or confusing the user with a lot of questions
or constraints in locating disks in certain drives.
A key feature of this search (and where this method of orien-
tation differs from the use of PATH or IF EXIST ) is that
searching on the disk drives is done "benignly". By this we mean
that SETDISK doesn't come to a grinding halt if an empty
disk drive is searched. Instead, it continues the search on
the rest of the drives. This further relieves the user from
having to locate certain disks on certain drives. The target
file may be on the B: or C: drive with the A: drive empty, and
SETDISK will find it without the annoying "ignore, abort, retry"
message. If the file is not found, then you may gently prod the
user to place the required disk "in any drive" and try again.
The syntax of the command line is the following:
findfile fname
where fname is a standard DOS path, filename, and extention.
If you include a drive specification (like "a:" for example),
the drive spec will be ignored by SETDISK.
SETDISK benignly searches all disk drives that are claimed
to be present by the system board switches, in order A:, B:, C:, and
D:. If the file is found, the disk number of the first disk on
which it was found is returned in errorlevel and may be tested
by a Batch File IF Subcommand. SETDISK also changes the DOS default
drive designator to the disk on which the file was found.
If fname found: errorlev = 0 if fname on A:
errorlev = 1 if fname on B:
errorlev = 2 if fname on C:
errorlev = 3 if fname on D:
(in all of above cases, the default
drive designator is changed to the
drive on which fname was found )
If fname not found: errorlev = 255
If fname is missing: errorlev = 255 , and a CNTRL BREAK
halts the Batch File
*
;
; constant equates
;
BEL_CHAR EQU 07 ;ascii BEL keycode
CR EQU 0DH ;ascii carriage return
LF EQU 0AH ;ascii line feed
TAB_CHAR EQU 09 ;ascii tab
BLANK_CHAR EQU ' ' ;ascii blank
COLON_CHAR EQU ':' ;ascii colon
NOT_FOUND_CODE EQU 255 ;errorlev returned for fname not
;found
DISK_MASK EQU 00C0H ;mask for equipment word's disk
;count field
;
;
; declare a relocatable segment. Follow the .COM file requirements
; of entry point at 100H and making all seg register references relative
; to CS (no relocatable values MOV'ed into segment registers).
;
;
COM_CODE SEGMENT
;
ORG 80H ;PSP offset 80: user's command line
PSP_CMD_LINE LABEL BYTE ;define a label for address refs
;
ORG 100H ;for COM file
;
;
ASSUME CS:COM_CODE,DS:COM_CODE ;tell assembler value of CS
ASSUME ES:COM_CODE ; DS, and ES
;
;
START PROC FAR ;FAR is meaningless; no RETS
;
MOV SI,OFFSET PSP_CMD_LINE ;offset of user's cmd line
SUB CX,CX ;clear CX
MOV CL,[SI] ;byte count of line
OR CL,CL ;zero?
JZ NO_FNAME ;jump if yes, no fname param
SUB BX,BX ;else zero index
;
; find first non-blank or non-tab character of command line
;
STRIP_BLANKS: INC SI ;point to next char
MOV AL,[SI] ;get next char from cmd line
CMP AL,BLANK_CHAR ;is it blank?
JE LOOP_BLANKS ;jump if yes, keep looking
CMP AL,TAB_CHAR ;is it a tab?
JNE GOT_NON_BLANK ;jump if not, first non-blank
LOOP_BLANKS: LOOP STRIP_BLANKS ;else keep looking
;
; fname is missing from command line (all blanks or tabs, or else
; zero characters on line
;
NO_FNAME: MOV DX,OFFSET ERROR_MESSAGE ;adr offset of error message
MOV AH,9 ;DOS fn call, "print string"
INT 21H ;call DOS
INT 23H ;cause a control break, cause
;this is probably a bug in
;batch file creation.
JMP NO_FILE_EXIT ;then exit with errorlevel =
; "NOT_FOUND_CODE"
;
; found first non-blank/tab character on command line
; at [SI][BX] . Check for disk designator " n: " and
; "strip" it from string by moving up pointer and decreasing
; remaining bytes count.
;
GOT_NON_BLANK: CMP BYTE PTR [SI+1],COLON_CHAR ;2nd non-blank char ":"?
JNE ADD_DRIVE ;if not, [SI] is start of strng
INC SI ;else strip off the drive spec
INC SI
DEC CX ;and decr remaining byte count
JZ NO_FNAME ;if string hits zero bytes left,
DEC CX
JZ NO_FNAME ; it's a "no param" error
;
; SI now points to start of ASCIIZ string that we want to use as
; the path/file name to search drives for
;
; Put a byte of zeros at the end of string, and an "A:" in front
; of string to initialize search.
;
ADD_DRIVE: MOV BX,CX ;number of bytes remaining
MOV BYTE PTR [SI][BX],0 ;points to 1 char past end
; of string
MOV BYTE PTR [SI-2],'A' ;"A:" in front of string
MOV BYTE PTR [SI-1],':'
;
; Replace the current critical error handler with our own
;
; First, get the address of the critical error handler assigned
; by "parent" process (probably system) to this process. Save its
; address, so that we can use it if our handler is handed a non-disk
; error ( "we don't do non-disk errors ..." )
;
MOV AH,35H ;DOS fn "get vector"
MOV AL,24H ;"critical error" vector no.
INT 21H ;call DOS
MOV WORD PTR PARENT_HAND,BX ;save offset vector adr
MOV WORD PTR PARENT_HAND+2,ES ;save seg vector adr
;
; Now, take control of critical error vector by assigning a handler
; to the vector address.
;
; DOS will restore the "parent"'s vector when this process returns to
; DOS.
;
MOV DX,OFFSET CRIT_HAND ;address of handler
MOV AL,24H ;the vector to be replaced
MOV AH,25H ;DOS fn call "ret int vector"
INT 21H ;call DOS and replace vector
;
; Get the number of drives that DOS knows about
; Dont disturb the current default disk setting when getting number
; of drives from DOS.
;
MOV AH,19H ;DOS fn "get current disk"
INT 21H ;current disk retd in AL
MOV DL,AL ;cur disk in DL for next call
MOV AH,0EH ;DOS fn "sel disk, return numb"
INT 21H ;number of drives retd in AL
SUB CH,CH ;clear CH
MOV CL,AL ;number of drives
INC CX ;is now (1,2,3, or 4)
;
; Now loop through all drives present, trying to find the file
; (using fn call 4EH) on each drive. If successful, return the
; disk number to caller in errorlevel.
;
; If not successful, return errorlevel = NOT_FOUND_CODE
;
MOV DX,SI ;offset adr of drive spec and
DEC DX ; filename
DEC DX
FIND_FILE: MOV AH,4EH ;DOS fn "find first file"
PUSH CX ;save the loop count
SUB CX,CX ;attribute says search
;"normal" files only
PUSH [SI-2] ;save drive letter (DOS call
;destroys it if file found)
INT 21H ;call DOS
POP [SI-2] ;restore drive letter
POP CX ;restore loop count
JNC FOUND_FILE ;if carry not set, then search
;was successful - jump.
INC BYTE PTR [SI-2] ;increment drive letter char
LOOP FIND_FILE ;and look on next drive
;
; did not find file. Return NOT_FOUND_CODE in errorlevel
;
NO_FILE_EXIT: MOV AL,NOT_FOUND_CODE ;file not found on any drive
EXIT: MOV AH,4CH ;DOS fn call to exit w/ errlev
INT 21H ;call DOS and exit
;
; found the file. Retrieve the drive letter used in this last call,
; map it to disk number (A = 0, B = 1, etc) and return it in errorlevel.
;
FOUND_FILE: MOV AL,[SI-2] ;get the drive letter (upper
;case ascii code)
SUB AL,'A' ;map it to 0,1,2,3
;
; Set the default drive designator to the drive on which the file
; was found
;
PUSH AX ;save AL
MOV DL,AL ;drive number (0,1,2,...)
MOV AH,0EH ;DOS fn "select disk"
INT 21H ;call DOS and set default
POP AX ;restore AL
JMP EXIT ;and return it in errorlevel
START ENDP
page
;
; CRIT_HAND Critical Error Handler
;
; This handler will be called by DOS functions when any critical
; error (disk or non-disk) occurs during DOS INT 21H calls that
; are made during execution of this process.
;
; We only want to ignore disk errors, so we first test if the disk
; is the cause of error.
;
; If not a disk error, we jump to the parent's critical error handler
; (we JMP so that stack looks as if we were never there).
;
; If it is a disk error, we return an IGNORE code to the calling
; DOS function. The effect of all this is that when a DOS function
; tries to access a disk drive that has a door open, or no disk, or
; disk is unformatted, or disk is garbled, etc, the DOS function will
; simply give up and return to the function's caller "empty handed".
; There will be no "abort, retry, ignore" message from the critical
; error handler.
;
; on entry: Bit 7 of AH = 0 if disk error
; = 1 if not a disk error
;
; on exit: If disk error, we set AL = 0, "ignore error"
;
; registers affected: AH, AL
;
CRIT_HAND PROC FAR ;RETS are typed FAR
TEST AH,80H ;bit 7 set?
JNZ NOT_DISK ;jump if yes,not disk error,
;don't treat it
;
; Treatment of disk errors is easy, just tell system to ignore them
;
SUB AL,AL ;zero AL, "ignore" code
IRET ;caller used INT so we IRET
;
; It was not a disk error, so let the "parent" critical error handler
; treat it by JMPing to its address that we saved.
;
; We JMP so we dont disturb the stack. Stack looks like we were
; never called.
;
NOT_DISK: JMP DWORD PTR PARENT_HAND ;jump to parent crit err hand
;
CRIT_HAND ENDP
;
;
; temporary storage of parent's critical handler address
;
PARENT_HAND DD 1 DUP(?) ;double word for FAR address
;
;
;
; error message string
;
ERROR_MESSAGE DB CR,LF,'***** No filename was given with '
DB 'SETDISK *****',CR,LF,'$'
;
;
COM_CODE ENDS
END START
Ä├╣ QÜ└éÄ^■ïσ]╦MW_F